package com.ts.api.module.match.plan.apply;

import com.gitee.apanlh.util.base.CollUtils;
import com.gitee.apanlh.util.base.Eq;
import com.gitee.apanlh.util.base.IteratorUtils;
import com.gitee.apanlh.util.dataformat.JsonUtils;
import com.gitee.apanlh.util.date.DateUtils;
import com.gitee.apanlh.util.valid.ValidParam;
import com.ts.api.common.constant.api.ApiEnum;
import com.ts.api.common.constant.product.ProductPlanVersionMode;
import com.ts.api.common.constant.productflow.ProductApplyFlowSrcTypeEnum;
import com.ts.api.common.constant.productflow.ProductApplyFlowStatusEnum;
import com.ts.api.common.constant.protocol.UserProtocolEnum;
import com.ts.api.common.redis.ApiMatchPhoneMaskRedisKey;
import com.ts.api.common.redis.entity.ApiMatchPhoneMaskRedisCache;
import com.ts.api.common.util.H5DomainUrlUtils;
import com.ts.api.exp.ApiMsgException;
import com.ts.api.module.api.convert.core.http.client.ApiHttpMessage;
import com.ts.api.module.api.convert.plan.http.ApiPlanHttpHandler;
import com.ts.api.module.api.convert.platform.entity.RespPlatformMultiPhoneMaskDataExchange;
import com.ts.api.module.api.convert.platform.entity.RespPlatformPhoneMaskDataExchange;
import com.ts.api.module.api.convert.platform.entity.RespPlatformPhoneMd5DataExchange;
import com.ts.api.module.api.entity.ApiUserRequest;
import com.ts.api.module.api.entity.bo.ApiKeyAmountBO;
import com.ts.api.module.api.service.ApiBizRequiredService;
import com.ts.api.module.api.service.ApiKeyAmountService;
import com.ts.api.module.api.service.ApiUserRegister;
import com.ts.api.module.channel.entity.po.ChannelUserRegisterPO;
import com.ts.api.module.match.plan.internal.distribute.model.PlanDistributeResult;
import com.ts.api.module.product.entity.bo.ProductAmountBO;
import com.ts.api.module.product.entity.po.ProductApplyFlowPO;
import com.ts.api.module.product.entity.po.ProductPO;
import com.ts.api.module.product.entity.po.ProductPlanPO;
import com.ts.api.module.product.service.ProductAmountService;
import com.ts.api.module.product.service.ProductPlanTypeService;
import com.ts.api.module.protocol.entity.po.ProductProtocolPO;
import com.ts.api.module.protocol.entity.po.UserProtocolPO;
import com.ts.api.module.protocol.entity.qo.ProductProtocolQO;
import com.ts.api.module.protocol.service.ProductProtocolService;
import com.ts.api.module.protocol.service.UserProtocolService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;

/**
 *  渠道计划进件业务
 *  TODO 临时完成业务，后续改造
 *  @author Pan
 */
@Service
public class PlanApplyService {

    @Autowired
    private ApiBizRequiredService apiBizRequiredService;
    @Autowired
    private ApiKeyAmountService apiKeyAmountService;
    @Autowired
    private ProductPlanTypeService productPlanTypeService;
    @Autowired
    private ApiUserRegister apiUserRegister;
    @Autowired
    private ProductAmountService productAmountService;
    @Autowired
    private ApiPlanHttpHandler apiPlanHttpHandler;
    @Autowired
    private UserProtocolService userProtocolService;
    @Autowired
    private ProductProtocolService productProtocolService;

    public void wakeApply(ApiUserRequest apiUserRequest, ChannelUserRegisterPO userRegisterPO, PlanDistributeResult planDistributeResult) {
        String phoneMd5 = userRegisterPO.getPhoneMd5();
        String phone = userRegisterPO.getPhone();

        ProductPO productPO = planDistributeResult.getProductPO();
        ProductPlanPO productPlanPO = planDistributeResult.getProductPlanPO();

        //  获取撞库成功流程数据
        ProductApplyFlowPO dataExchangeSucFlow = planDistributeResult.getCurrentDistributeFlow();
        Long loanChannelId = dataExchangeSucFlow.getLoanChannelId();

        //  记录进件流程
        ProductApplyFlowPO insertProductApplyFlowPO = new ProductApplyFlowPO();
        insertProductApplyFlowPO.setApiClientId(dataExchangeSucFlow.getApiClientId());
        insertProductApplyFlowPO.setLoanChannelId(dataExchangeSucFlow.getLoanChannelId());
        insertProductApplyFlowPO.setLoanProductId(dataExchangeSucFlow.getLoanProductId());
        insertProductApplyFlowPO.setLoanProductPlanId(dataExchangeSucFlow.getLoanProductPlanId());
        insertProductApplyFlowPO.setReqId(dataExchangeSucFlow.getReqId());
        insertProductApplyFlowPO.setSrcType(ProductApplyFlowSrcTypeEnum.API.getType());
        insertProductApplyFlowPO.setStatus(ProductApplyFlowStatusEnum.APPLY_ERROR.getType());
        insertProductApplyFlowPO.setPhoneMd5(dataExchangeSucFlow.getPhoneMd5());
        insertProductApplyFlowPO.setCreateTime(DateUtils.currentTime());
        insertProductApplyFlowPO.setBizStatus("0");
        insertProductApplyFlowPO.setAreaName(apiUserRequest.getCity());
        insertProductApplyFlowPO.setAreaCode(apiUserRequest.getAreaCode());

        //  1.验证计划时间
        boolean hasLimitTime = apiBizRequiredService.hasLimitTime(insertProductApplyFlowPO, productPlanPO, ProductApplyFlowStatusEnum.APPLY_BIZ_ERROR);
        if (!hasLimitTime) {
            return ;
        }

        //  2.验证机构余额是否足够本次扣款
        boolean requiredProductAmount = apiBizRequiredService.requiredProductAmount(insertProductApplyFlowPO, productPlanPO, ProductApplyFlowStatusEnum.APPLY_BIZ_ERROR);
        if (!requiredProductAmount) {
            return ;
        }

        //  3.验证空号检测
        boolean requiredPhoneStatus = apiBizRequiredService.requiredPhoneStatus(insertProductApplyFlowPO, productPlanPO, phone);
        if (!requiredPhoneStatus) {
            return ;
        }

        //  是否本地机构计划
        if (productPlanTypeService.hasLocalOrgPlan(productPO, productPlanPO)) {
            insertProductApplyFlowPO.setCallUrl("本地甲方CRM");
        }

        //  API机构计划或平台计划
        boolean hasPlatform = productPlanTypeService.hasPlatformPlan(productPlanPO);
        boolean hasApiOrgPlan = productPlanTypeService.hasApiOrgPlan(productPO, productPlanPO);

        if (hasPlatform || hasApiOrgPlan) {
            Long reqId = insertProductApplyFlowPO.getReqId();

            //  获取进件applyId值
            String saveApplyKey = ApiMatchPhoneMaskRedisKey.getChannelDataExchangeApplyIdKey(loanChannelId, productPO.getId(), productPlanPO.getId(), phoneMd5);
            ApiMatchPhoneMaskRedisCache apiMatchPhoneMaskRedisCache = ApiMatchPhoneMaskRedisKey.CHANNEL_DATA_EXCHANGE_PHONE_MASK_APPLY_ID.get(saveApplyKey, ApiMatchPhoneMaskRedisCache.class);
            if (ValidParam.isNotNull(apiMatchPhoneMaskRedisCache)){
                String applyId = apiMatchPhoneMaskRedisCache.getApplyId();
                apiUserRequest.setApplyId(applyId);
            }

            //  设置API参数数据
            apiUserRequest.setProductId(insertProductApplyFlowPO.getLoanProductId());
            apiUserRequest.setProductPlanId(insertProductApplyFlowPO.getLoanProductPlanId());
            apiUserRequest.setLoanChannelId(insertProductApplyFlowPO.getLoanChannelId());
            apiUserRequest.setReqId(reqId.toString());

            //  发送进件
            ApiHttpMessage httpMessage = apiPlanHttpHandler.sendApply(apiUserRequest, productPO, productPlanPO);
            insertProductApplyFlowPO.setCallUrl(productPO.getApiApplyUrl());
            insertProductApplyFlowPO.setSourceReqData(httpMessage.getSourceRequestBody());
            insertProductApplyFlowPO.setReqData(String.valueOf(httpMessage.getRequestBody()));
            insertProductApplyFlowPO.setRespData(httpMessage.getResponseBody());
            insertProductApplyFlowPO.setRespCode(String.valueOf(httpMessage.getRespCode()));

            //  是否返回HTTP异常
            boolean hasHttpExp = apiBizRequiredService.hasHttpExp(insertProductApplyFlowPO, httpMessage, true, ProductApplyFlowStatusEnum.APPLY_ERROR);
            if (hasHttpExp) {
                throw new ApiMsgException(ApiEnum.API_RECEIVE_ORG_ERROR);
            }

            //  是否进件返回失败
            boolean hasHttpRespBizSuc = apiBizRequiredService.hasHttpRespBizSuc(insertProductApplyFlowPO, httpMessage, true, ProductApplyFlowStatusEnum.APPLY_ERROR);
            if (!hasHttpRespBizSuc) {
                throw new ApiMsgException(ApiEnum.API_RECEIVE_ORG_FAIL);
            }

            //  记录下游用户协议
            if (hasPlatform) {
                ProductProtocolQO productProtocolQO = new ProductProtocolQO();
                productProtocolQO.setProductId(productPO.getId());
                productProtocolQO.setHasNeedText(true);
                List<ProductProtocolPO> listProductProtocol = productProtocolService.list(productProtocolQO);

                //  添加下游协议
                IteratorUtils.array(listProductProtocol, productProtocolPO -> {
                    String productTemplate = productProtocolPO.getText();

                    //  查询平台模板
                    UserProtocolPO userProtocolPO = new UserProtocolPO();
                    userProtocolPO.setLoanChannelId(loanChannelId);
                    userProtocolPO.setLoanProductId(productPO.getId());
                    userProtocolPO.setLoanProductPlanId(productPlanPO.getId());
                    userProtocolPO.setLoanProductProtocolId(productProtocolPO.getId());
                    userProtocolPO.setLoanUserId(userRegisterPO.getId());
                    userProtocolPO.setPhoneMd5(phoneMd5);
                    userProtocolPO.setUrl(H5DomainUrlUtils.createUserProtocolUrl(productPlanPO.getId(), phoneMd5));
                    userProtocolPO.setType(UserProtocolEnum.PRODUCT.getType());
                    userProtocolPO.setCreateTime(DateUtils.currentTime());

                    //  填充协议模板
                    //  md5模式
                    if (ProductPlanVersionMode.MD5.hasVersionMode(productPlanPO)) {
                        RespPlatformPhoneMd5DataExchange md5DataExchange = RespPlatformPhoneMd5DataExchange.parseByJson(dataExchangeSucFlow.getRespData());
                        String appendedTemplate = userProtocolService.appendTemplate(userRegisterPO, productTemplate, md5DataExchange);
                        userProtocolPO.setText(appendedTemplate);
                        userProtocolService.insert(userProtocolPO);
                    }

                    //  掩码模式
                    if (Eq.objectOr(productPlanPO.getVersionMode(),
                            ProductPlanVersionMode.PHONE_MASK_8.getVersionMode(),
                            ProductPlanVersionMode.PHONE_MASK_9.getVersionMode(),
                            ProductPlanVersionMode.PHONE_MASK_10.getVersionMode())) {

                        //  填充模板
                        RespPlatformMultiPhoneMaskDataExchange respMultiPhoneMask = JsonUtils.toBean(dataExchangeSucFlow.getRespData(), RespPlatformMultiPhoneMaskDataExchange.class);
                        String applyId = apiUserRequest.getApplyId();
                        //  获取原始撞库apply对应进件apply数据
                        List<RespPlatformPhoneMaskDataExchange> listPhoneMask = respMultiPhoneMask.getListPhoneMask();
                        RespPlatformPhoneMaskDataExchange findPhoneMask = CollUtils.findOne(listPhoneMask, phoneMaskDataExchange -> phoneMaskDataExchange.getApplyId().equals(applyId));

                        String appendedTemplate = userProtocolService.appendTemplatePhoneMask(userRegisterPO, productTemplate, findPhoneMask);
                        userProtocolPO.setText(appendedTemplate);
                        userProtocolService.insert(userProtocolPO);
                    }
                });
            }
        }

        //  用户数据关联机构并记录流程数据
        insertProductApplyFlowPO.setStatus(ProductApplyFlowStatusEnum.USER_ACCEPT.getType());
        insertProductApplyFlowPO.setBizStatus("1");

        //  分发的是本地CRM已经有件时则返回进件失败，只要一次件
        if (productPlanTypeService.hasLocalOrgPlan(productPO, productPlanPO)) {
            try {
                apiUserRegister.uniqueBindProductUser(insertProductApplyFlowPO, userRegisterPO.getId());
            } catch (Exception e) {
                throw new ApiMsgException(ApiEnum.API_USER_INFO_EXIST.format("进件"));
            }
        } else {
            //  如果分发的是平台/API机构计划则忽略限制
            apiUserRegister.multiBindProductUser(insertProductApplyFlowPO, userRegisterPO.getId());
        }

        //  主体-单次计费业务
        BigDecimal originalPrice = null;
        ProductAmountBO productAmountBO = new ProductAmountBO();

        //  平台计划-解析撞库成功时的单价
        if (hasPlatform) {
            //  md5模式
            if (ProductPlanVersionMode.MD5.hasVersionMode(productPlanPO)) {
                RespPlatformPhoneMd5DataExchange md5DataExchange = RespPlatformPhoneMd5DataExchange.parseByJson(dataExchangeSucFlow.getRespData());
                originalPrice = md5DataExchange.getPrice();
            }

            //  掩码模式
            if (Eq.objectOr(productPlanPO.getVersionMode(),
                    ProductPlanVersionMode.PHONE_MASK_8.getVersionMode(),
                    ProductPlanVersionMode.PHONE_MASK_9.getVersionMode(),
                    ProductPlanVersionMode.PHONE_MASK_10.getVersionMode())) {

                //  找到原始进件applyId
                String applyId = apiUserRequest.getApplyId();

                RespPlatformMultiPhoneMaskDataExchange respMultiPhoneMask = JsonUtils.toBean(dataExchangeSucFlow.getRespData(), RespPlatformMultiPhoneMaskDataExchange.class);
                List<RespPlatformPhoneMaskDataExchange> listPhoneMask = respMultiPhoneMask.getListPhoneMask();

                //  获取原始撞库apply对应进件apply数据
                RespPlatformPhoneMaskDataExchange findPhoneMaskDataExchange =
                        CollUtils.findOne(listPhoneMask, phoneMaskDataExchange -> phoneMaskDataExchange.getApplyId().equals(applyId));
                originalPrice = findPhoneMaskDataExchange.getPrice();
            }
            productAmountBO.setOriginalPrice(originalPrice);
        }

        productAmountBO.setProductId(productPlanPO.getLoanProductId());
        productAmountBO.setProductPlanId(productPlanPO.getId());
        productAmountBO.setUserId(userRegisterPO.getId());
        productAmountBO.setPhoneMd5(userRegisterPO.getPhoneMd5());
        productAmountBO.setLoanChannelId(dataExchangeSucFlow.getLoanChannelId());
        productAmountBO.setApiClientId(dataExchangeSucFlow.getApiClientId());
        productAmountBO.setHasPlatform(hasPlatform);
        productAmountBO.setHasLocalExist(Boolean.FALSE);
        productAmountService.deduct(productAmountBO);

        //  API渠道扣款
        ApiKeyAmountBO apiKeyAmountBO = new ApiKeyAmountBO();
        apiKeyAmountBO.setProductId(productPlanPO.getLoanProductId());
        apiKeyAmountBO.setProductPlanId(productPlanPO.getId());
        apiKeyAmountBO.setUserId(userRegisterPO.getId());
        apiKeyAmountBO.setPhoneMd5(userRegisterPO.getPhoneMd5());
        apiKeyAmountBO.setLoanChannelId(dataExchangeSucFlow.getLoanChannelId());
        apiKeyAmountBO.setApiClientId(dataExchangeSucFlow.getApiClientId());
        apiKeyAmountBO.setPlanPrice(new BigDecimal("0.00"));
        apiKeyAmountBO.setHasPlatform(true);
        apiKeyAmountBO.setHasLocalExist(true);
        apiKeyAmountService.deduct(apiKeyAmountBO);
    }
}
